<?php
class Upload {
	/*文件名 上传时原文件名称*/
	public $fileName;
	/*文件类型*/
	public $fileType;
	/*文件后缀*/
	public $fileExt;
	/*文件大小*/
	public $fileSize;
	/*只允许的类型*/
	public $allowType = array ();
	/*只允许的后缀*/
	public $allowExt = array ();
	/*允许的文件大小*/
	public $allowSize = 2147483648; //byte
	/*受限制的类型*/
	public $limitType = array ();
	/*受限制的后缀*/
	public $limitExt = array ('php', 'exe', 'html', 'htm', 'xhtml' );	
	/*错误代码*/
	private $errorCode;
	/*多文件上传*/
	private $multi;
	/*次序*/
	private $order;
	/**
	 *上传文件,成功返回目标文件名，失败返回false
	 *
	 *@name string 控件名称
	 *@destination string 目标路径
	 *@filename string or boolean目标文件名 true:保留原名 false:程序自动设置 string:自定义名字
	 *@return string or false
	 */
	public function uploadFile($name, $destination = './', $filename = false) {
		$destination =  APPLICATION_PATH . '/../public/upload/file/';
		$upload_name = $_FILES [$name] ["name"];
		$file_tmp_name = $_FILES [$name] ["tmp_name"];
		
		$place = strrpos ( $upload_name, '.' );
		
		$this->multi = false;
		$this->fileName = substr ( $upload_name, 0, $place );
		$this->fileExt = substr ( $upload_name, $place + 1 );
		
		$this->fileType = $_FILES [$name] ["type"];
		$this->fileSize = $_FILES [$name] ["size"];
		$this->errorCode = $_FILES [$name] ["error"];
		
		$filename = $filename === true ? $this->fileName : ($filename === false ? uniqid ( rand (), true ) : $filename);
		$dest_filename = trim ( $filename . '.' . $this->fileExt, '.' );
		$dest_file = $destination . "/" . $dest_filename;
		$dest_file = strtr ( $dest_file, '//', '/' );
		
		if ($this->checkUpload () && $this->copyFile ( $file_tmp_name, $dest_file )) {
			return $dest_filename;
		}
		
		return false;
	}
	
	/**
	 *上传文件,成功返回目标文件名数组，失败返回false
	 *
	 *@name string 控件名称
	 *@destination string 目标路径
	 *@filename array or boolean目标文件名 true:保留原名 false:程序自动设置 array():自定义名字顺序与控件顺序一致
	 *@trans boolean 事务上传 true:全部成功才返回成功，false:一个成功就返回成功
	 *@return array or false
	 */
	public function uploadMultiFile($name, $destination = './', $filename = false, $trans = true) {
		$destination =  APPLICATION_PATH . '/../public/upload/file/';
		$upload_names = $_FILES [$name] ["name"];
		//var_dump($upload_names);exit;
		$upload_list = array ();
		$dest_list = array ();
		$is_true = false;
		
		if (is_array ( $upload_names )) {
			
			$this->multi = true;
			foreach ( $upload_names as $k => $upload_name ) {
				$place = strrpos ( $upload_name, '.' );
				$file_tmp_names [$k] = $_FILES [$name] ["tmp_name"] [$k];
				
				$this->fileName [$k] = substr ( $upload_name, 0, $place );
				$this->fileExt [$k] = substr ( $upload_name, $place + 1 );
				
				$this->fileType [$k] = $_FILES [$name] ["type"] [$k];
				$this->fileSize [$k] = $_FILES [$name] ["size"] [$k];
				$this->errorCode [$k] = $_FILES [$name] ["error"] [$k];
				$this->order = $k;
				
				$to_name = $filename === true ? $this->fileName [$k] : ($filename === false || empty ( $filename [$k] ) ? uniqid ( rand (), true ) : $filename);
				$dest_filename = trim ( $to_name . '.' . $this->fileExt [$k], '.' );
				
				if ($this->checkUpload ()) {
					$upload_list [$k] = array ('from' => $file_tmp_names [$k], 'to' => $dest_filename );
				} else {
					if ($trans)
						return false;
				}
			}
			
			foreach ( $upload_list as $k => $list ) {
				$dest_file = $destination . "/" . $list ['to'];
				$dest_file = str_replace ( '//', '/', $dest_file );
				
				$this->order = $k;
				
				if ($this->copyFile ( $list ['from'], $dest_file )) {
					$is_true = true;
					$dest_list [$k]["to"] = $list ['to'];
					$dest_list [$k]["from"] = $this->fileName [$k].".". $this->fileExt [$k];
				} else {
					if ($trans) {
						for($i = $k - 1; $i >= 0; $i) {
							$this->unlink ( $destination . '/' . $dest_list [$i] );
						}
						return false;
					}
				}
			}
		} else {
			return $this->uploadFile ( $name, $destination, $filename );
		}
		//print_r($dest_list);exit;
		if ($is_true)
			return $dest_list;
		
		return false;
	}
	
	public function unlink($file) {
		$file = str_replace ( '//', '/', $file );
		return ! empty ( $file ) && @unlink ( $file );
	}
	
	private function copyFile($orig_file, $dest_file) {
		if (@move_uploaded_file ( $orig_file, $dest_file ) || @copy ( $orig_file, $dest_file )) {
			$this->setMsg ( '文件上传成功' );
			return true;
		}
		
		$this->setMsg ( '文件上传失败' );
		return false;
	}
	
	private function checkUpload() {
		if ($this->multi) {
			$order = $this->order;
			$filename = $this->fileName [$order];
			$error_code = $this->errorCode [$order];
			$file_type = $this->fileType [$order];
			$file_ext = $this->fileExt [$order];
			$file_size = $this->fileSize [$order];
		} else {
			$filename = $this->fileName;
			$error_code = $this->errorCode;
			$file_type = $this->fileType;
			$file_ext = $this->fileExt;
			$file_size = $this->fileSize;
		}
		
		if (empty ( $filename )) {
			$this->setMsg ( '没有文件被上传' );
			return false;
		}
		
		$bool = true;
		switch ($error_code) {
			case 0 :
				//其值为 0，没有错误发生，文件上传成功。
				break;
			case 1 :
				$this->setMsg ( '上传的文件超过了服务器限制的值' );
				$bool = false;
				break;
			case 2 :
				$this->setMsg ( '上传文件的大小超过了指定选项指定的值' );
				$bool = false;
				break;
			case 3 :
				$this->setMsg ( '文件只有部分被上传' );
				$bool = false;
				break;
			case 4 :
				$this->setMsg ( '没有文件被上传' );
				$bool = false;
				break;
			case 6 :
				$this->setMsg ( '找不到临时文件夹' );
				$bool = false;
				break;
			case 7 :
				$this->setMsg ( '文件写入失败' );
				$bool = false;
				break;
		}
		
		if (! $bool)
			return false;
		
		if (! empty ( $this->allowType )) {
			if (! in_array ( $file_type, $this->allowType )) {
				$this->setMsg ( '不支持此文件类型，请重新选择' );
				return false;
			}
		}
		
		if (! empty ( $this->allowExt )) {
			if (! in_array ( $file_ext, $this->allowExt )) {
				$this->setMsg ( '不支持的后缀名，请重新选择' );
				return false;
			}
		}
		
		if (in_array ( $file_type, $this->limitType )) {
			$this->setMsg ( '不支持此文件类型，请重新选择' );
			return false;
		}
		
		if (in_array ( $file_ext, $this->limitExt )) {
			$this->setMsg ( '不支持的后缀名，请重新选择' );
			return false;
		}
		
		if ($file_size > $this->allowSize) {
			$this->setMsg ( '文件容量太大' );
			return false;
		}
		
		return true;
	}
	
	private function setMsg($msg) {
		if ($this->multi)
			$this->message [$this->order] = $msg;
		else
			$this->message = $msg;
	}
}